﻿using System;
using System.Collections.Generic;

namespace IFramework
{
    public class Observe : IObserve
    {
        private readonly Type observeType;
        public Type ObserveType
        {
            get
            {
                return observeType;
            }
        }

        public Observe(Type observeType)
        {
            this.observeType = observeType;
        }
        private Queue<IObserver> observers = new Queue<IObserver>();
        private Queue<IObserver> helpQueue = new Queue<IObserver>();
        public void AddObserver(IObserver observer)
        {
            lock (helpQueue)
            {
                lock (observers)
                {
                    if (observers.Contains(observer) || helpQueue.Contains(observer)) return;
                    observers.Enqueue(observer);
                }
            }
        }
        public void RemoveObserver(IObserver observer)
        {
            lock (helpQueue)
            {
                lock (observers)
                {
                    if (observers.Contains(observer))
                    {
                        while (observers.Peek() != observer)
                        {
                            helpQueue.Enqueue(observers.Dequeue());
                        }
                        observers.Dequeue();
                    }
                    else if (helpQueue.Contains(observer))
                    {
                        while (helpQueue.Peek() != observer)
                        {
                            observers.Enqueue(helpQueue.Dequeue());
                        }
                        helpQueue.Dequeue();
                    }
                }
            }

        }
        private int observerCount;
        public void Notify(EventArgs args, int code, params object[] message)
        {
            lock (observers)
            {
                lock (helpQueue)
                {
                    observerCount = observers.Count;
                    while (observers.Count != 0)
                    {
                        observers.Peek().Listen(args, observeType, code, message);
                        helpQueue.Enqueue(observers.Dequeue());
                    }
                    while (helpQueue.Count != observerCount)
                    {
                        helpQueue.Peek().Listen(args, observeType, code, message);
                        observers.Enqueue(observers.Dequeue());
                    }
                }

            }
        }

        public void Dispose()
        {
            observers.TrimExcess();
            observers.Clear();
            helpQueue.TrimExcess();
            helpQueue.Clear();
            observers = null;
            helpQueue = null;
        }
    }
}